home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Communication / Weather / Source / Storm.m < prev    next >
Text File  |  1993-11-14  |  11KB  |  543 lines

  1. /*
  2.  * Object to peck on a remote network weather service.
  3.  *
  4.  * Michael Hawley
  5.  * MIT Media Laboratory
  6.  * 20 Ames Street
  7.  * Cambridge, MA 02139
  8.  * mike@media-lab.mit.edu
  9.  * Copyright (c) 1991 MIT Media Laboratory
  10.  * Burn before reading!  This means you!!
  11.  *
  12.  * Please forward any comments/revisions.
  13.  * Keep in mind that this was a one-day knock off;
  14.  * much of the complexity is due to the fact that
  15.  * we have to parse a telnet conversation that was
  16.  * never intended for such.
  17.  */
  18.  
  19. #import "Storm.h"
  20. #import "Process.h"
  21. #import "MyMenuCell.h"
  22. #import "Defaults.h"
  23. #import "License.h"
  24. #import "util.h"
  25. #import "state.h"
  26.  
  27. @implementation Storm
  28.  
  29. static int localblank(char *s){
  30.     while (*s && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')) s++;
  31.     return *s? 0 : 1;
  32. }
  33.  
  34. static id _status;
  35. static id _Parrot;    /* compiler hated _P ! */
  36. static id _text, _scroll;
  37. static id fid = (id)0;
  38. static int canconvert = 0;
  39. static id me;
  40.  
  41.  
  42.  
  43. char *
  44. path(char *s)
  45. /*
  46.  * if 's' is in [NXArgv[0]], return [NXArgv[0]]/s.
  47.  * (for looking up internal commands and files in .../Opener.app/...).
  48.  */
  49. {
  50.     char t[1024], *q, *r;
  51.     static char p[1024];
  52.     extern char **NXArgv;
  53.     *t = '\0';
  54.     sscanf(s,"%s",t);
  55.     if (!*t || *t=='(') return s;
  56.     r = s + strlen(t);
  57.     strcpy(p,*NXArgv);
  58.     if (q=rindex(p,'/'))
  59.         strcpy(q+1,t);
  60.     else
  61.         strcpy(p,t);
  62.     if (access(p,0)==0){
  63.         strcpy(p+strlen(p),r);
  64.         return p;
  65.     }
  66.     return s;
  67. }
  68.  
  69. void message(char *fmt, ...) {
  70.     char p[1024];
  71.     va_list ap;
  72.     
  73.     va_start(ap, fmt);
  74.     vsprintf(p,fmt,ap);
  75.     [_status setStringValue:p];
  76.     [_status display];
  77.     NXPing();
  78.     va_end(ap);
  79. }
  80.  
  81. static int eq(char *a, char *b){ return strncmp(a,b,strlen(b))==0; }
  82.  
  83. static char *localstrindex(char *s, char *t){
  84.     int n = strlen(t);
  85.     if (s) while (*s)
  86.     if (!strncmp(s, t, n))
  87.         return s;
  88.     else
  89.         s++;
  90.     return (char *)0;
  91. }
  92.  
  93. void Put(char *fmt, ...) {
  94.     va_list ap;
  95.     char p[1024];
  96.     
  97.     va_start(ap, fmt);
  98.     vsprintf(p, fmt, ap);
  99.     if (Verbose) printf("+ %s\n",p);
  100.     if (_Parrot) [_Parrot puts:p];
  101.     va_end(ap);
  102. }
  103.  
  104.  
  105. static char *
  106. get(id P, char *s, int n) {
  107.     [P gets:s:n];
  108.     if (*s && Verbose) printf("> %s",s);
  109.     return *s? s : (char *)0; 
  110. }
  111.  
  112. char *
  113. pgets(char *s, int n) {
  114.     [_Parrot gets:s:n];
  115.     return *s? s : (char *)0; 
  116. }
  117.  
  118.  
  119. char *
  120. Flush(char *s) {
  121.     static char t[1024];
  122.     if (_Parrot) return (char *)0;
  123.     while (get(_Parrot,t,sizeof t))
  124.         if (localstrindex(t,s)) return t;
  125.     sleep(1);
  126.     while (get(_Parrot,t,sizeof t))
  127.         if (localstrindex(t,s)) return t;
  128.     return (char *)0;
  129. }
  130.  
  131. - enable:(BOOL)b {
  132.     [attachB setIcon:b? "plug" : "unplug"];
  133.     return self;
  134. }
  135.  
  136.  
  137.  
  138. - initMatrix {
  139.     // from the nib file, we have the help text; keep a pointer to it.
  140.     _text = helpText = [scrollView docView];
  141.     [_text setDelegate:self];
  142.     [_text setMarginLeft:6.0 right:6.0 top:0.0 bottom:0.0];
  143.     [_text notifyAncestorWhenFrameChanged:YES];
  144.     return self;
  145. }
  146.  
  147. - setScrollView:anObject {
  148.     _scroll = scrollView = anObject;
  149.     [self initMatrix];
  150.     return self;
  151. }
  152.  
  153. - textWillConvert:textObject fromFont:from toFont:to {
  154.     if (canconvert && strcmp(DefaultFont,[from name])==0 &&
  155.     atof(DefaultFontSize) == [from pointSize]){
  156.     strcpy(DefaultFont,[to name]);
  157.     sprintf(DefaultFontSize,"%f",[to pointSize]);
  158.     fid = to;
  159.     writeDefaults();
  160.     }
  161.     return to;
  162. }
  163.  
  164. void
  165. setText(char *s) {
  166.     static NXPoint origin = {0.0,0.0};
  167.     id w = [_scroll window];
  168.  
  169.     if (!fid){
  170.         fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
  171.     }
  172.     canconvert=0;
  173.     [w disableFlushWindow];
  174.     [_text setText:s];
  175.     [_text setSel:0:999999];
  176.     [_text setSelGray:0.0];
  177.     [_text setSelFont:fid];
  178.     [_text selectNull];
  179.     [_text scrollPoint:&origin];
  180.     [_scroll display];
  181.     [[w reenableFlushWindow] flushWindow];
  182.     NXPing();
  183.     canconvert=1;
  184. }
  185.  
  186. void openFile(char *s){ /* open 's' in workspace */
  187.     int ok = 0;
  188.     id p = [NXApp appSpeaker];
  189.     char t[512];
  190.  
  191.     sprintf(t,"\nThe file\n        %s\nwill open in the workspace.",s);
  192.     setText(t);
  193.     [p setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  194.     [p openFile:s ok:&ok];
  195.     if (!ok) sprintf(t,"\nCouldn't open: %s",s), setText(t);
  196. }
  197.  
  198. static int isRTF(char *s) {
  199.     int f = open(s,0);
  200.     if (f > 0){
  201.         char t[128];
  202.         int n = read(f,t,sizeof(t));
  203.         close(f);
  204.         if (n <= 0) return 0;
  205.         return strncmp(t,"{\\rtf",5)==0;
  206.     } else
  207.         return 0;
  208. }
  209.  
  210. void
  211. setFile(char *s) {
  212.     char *p = path(s);
  213.     NXStream *f = NXMapFile(p,NX_READONLY);
  214.     static NXPoint origin = {0.0,0.0};
  215.     id w = [_scroll window];
  216.  
  217.     canconvert=0;
  218.     if (!f) return ;
  219.     [w disableFlushWindow];
  220.  
  221.     if (isRTF(p)){
  222.     [_text setMonoFont:NO];
  223.     [_text readRichText:f];
  224.     } else {
  225.     [_text readText:f];
  226.         [_text setSel:0:999999];
  227.         [_text setSelGray:0.0];
  228.     if (!fid)
  229.         fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
  230.         [_text setSelFont:fid];
  231.         [_text selectNull];
  232.         canconvert=1;
  233.     }
  234.     NXCloseMemory(f,NX_FREEBUFFER);
  235.     [_text scrollPoint:&origin];
  236.     [_scroll display];
  237.     [[w reenableFlushWindow] flushWindow];
  238. }
  239.  
  240. - showHelp:sender {
  241.     setFile("info");
  242.     return self;
  243. }
  244.  
  245. #define Case break; case
  246.  
  247. static void squishRtn(char *s){
  248.     char *p = s;
  249.  
  250.     while (*p = *s++)
  251.         if (*p != '\r') ++p;
  252. }
  253.  
  254. static char *
  255. getLine(char *s, char *t){ /* read ...\n from s into t; return new s */
  256.     char *p = t;
  257.     *t = '\0';
  258.     squishRtn(s);
  259.     while (*s && *s != '\n') *p++ = *s++;
  260.     if (*s == '\n') *p++ = *s++;
  261.     *p++ = '\0';
  262.     if (*t == '\0') return (char *)0;
  263.     if (Verbose) printf("- %s",t);
  264.     return s;
  265. }
  266.  
  267. - processOutput:(char *)s {
  268.     static char prev[8192]="";
  269.     char t[1024], *p=prev;
  270.  
  271.     strcat(prev,s); s = t;
  272.     while ((p=getLine(p,s)) && 
  273.            (index(s,'\n') || strcmp(s+strlen(s)-2,": ")==0 ||
  274.                              strcmp(s+strlen(s)-1,":")==0))
  275.         execState(0,s);
  276.     strcpy(prev,localblank(s)?s:"");
  277.     return self;
  278. }
  279.  
  280. void Command(char *s) {
  281.     if (!_Parrot) {
  282.         substr(s,"$Site",Site);
  283.         _Parrot = [Process new:s delegate:me];
  284.     }
  285. }
  286.  
  287. - click:sender {
  288.     id c =  [[browser matrixInColumn:[browser lastColumn]] selectedCell];
  289.     if ([c isLeaf])
  290.         [c click:self];
  291.     return self;
  292. }
  293.  
  294. - click2:sender {
  295.     return self;
  296. }
  297.  
  298. - ensurelogin {
  299.     //if (!_Parrot) [self login:self];
  300.     return self;
  301. }
  302.  
  303.  
  304. int ensurelogin(void){
  305.     [me ensurelogin];
  306.     return _Parrot? 1 : 0;
  307. }
  308.  
  309. - login:sender {
  310.     if (_Parrot) [_Parrot free]; P = _Parrot = (id)0;
  311.     _status = status;
  312.     [self setFetch];
  313.     ReadState(path("menus"));
  314.     [browser setDelegate:self];
  315.     [browser setCellPrototype:[[MyMenuCell alloc] init]];
  316.     [browser loadColumnZero];
  317.     [browser setAction:@selector(click:)];
  318.     [browser setDoubleAction:@selector(click2:)];
  319.     [browser setTarget:self];
  320.     [attachB setIcon:"plug"];
  321.     runState("");
  322.     return self;
  323. }
  324.  
  325. - logout:sender {
  326.     if (P && _Parrot) setState("Detach"), runState("");
  327.     if (P) [P terminate:self];
  328.     _Parrot = P = (id)0;
  329.     [self enable:NO];
  330.     [attachB setIcon:"unplug"];
  331.     message("not connected.");
  332.     return self;
  333. }
  334.  
  335. void
  336. logout(void){
  337.     [me logout:me];
  338. }
  339.  
  340. - attach:sender {
  341.     if (eq((char *)[sender icon],"unplug")){
  342.         [self login:sender];
  343.     } else {
  344.         [self logout:sender];
  345.     }
  346.     return self;
  347. }
  348.  
  349. /*
  350.  * the buttons and commands to run at startup time.
  351.  */
  352. id Fetch[NumFetch];
  353.  
  354. int FetchSelected = -1;
  355.  
  356. - setFetch {
  357.     int i;
  358.     Fetch[0] = fetch1;
  359.     Fetch[1] = fetch2;
  360.     Fetch[2] = fetch3;
  361.     for (i=0;i<NumFetch;i++) [self setFetchText:i:FetchText[i]];
  362.     return self;
  363. }
  364.  
  365. - setFetchText:(int)i:(char *)s {
  366.     [Fetch[i] setStringValue:s];
  367.     strcpy(FetchText[i],s);
  368.     [Fetch[i] display];
  369.     return self;
  370. }
  371.  
  372. - setFetchText:(char *)s {
  373.     if (FetchSelected >= 0)
  374.         [self setFetchText:FetchSelected:s];
  375.     return self;
  376. }
  377.  
  378. void
  379. setFetchText(char *s) {
  380.     [me setFetchText:s];
  381. }
  382.  
  383. - setFetch:(int)i:(int)state {
  384.     [Fetch[i] setBackgroundGray:state?1.0:.666];
  385.     if (state) [self setFetchText:i:""];
  386.     else [Fetch[i] display];
  387.     return self;
  388. }
  389.  
  390. - hitRadio:sender {
  391.     int i;
  392.     int n = [sender selectedRow], state = [[sender selectedCell] state];
  393.     [self setFetch:n:state];
  394.     FetchSelected = state? n : -1;
  395.     for (i=0; i<NumFetch; i++){
  396.         if (i != n || !state){
  397.             [[sender cellAt:i:0] setState:0];
  398.             [self setFetch:i:0];
  399.         }
  400.     }
  401.     [sender display];
  402.     return self;
  403. }
  404.  
  405. void fetchReports(void ) {
  406.     int i;
  407.     char buf[80000], *p = buf;
  408.     while (pgets(buf,1024) && !localstrindex(buf,curMenuLast())) ;
  409.     *buf = '\0';
  410.     for (i=0;i<NumFetch;i++){
  411.        if (!localblank(FetchText[i])){
  412.            message("%s. . .",FetchText[i]);
  413.            fetchReport(FetchText[i],p);
  414.            if (p[0]){
  415.                p += strlen(p);
  416.                if (i < (NumFetch-1))
  417.                    strcpy(p,"\n===============================\n");
  418.                p += strlen(p);
  419.            }
  420.        }
  421.     }
  422.     squishRtn(buf);
  423.     squishwhite(buf);
  424.     if (*buf) setText(buf);
  425.     message("connected!");
  426. }
  427.  
  428. - setSite:thing {
  429.     openDefaults();
  430.     site = thing;
  431.     [site setTitle:Site];
  432.     return self;
  433. }
  434.  
  435. - hitSite:sender {
  436.     char *s = (char *)[[sender selectedCell] title];
  437.     strcpy(Site,s);
  438.     writeDefaults();
  439.     return self;
  440. }
  441.  
  442. /*
  443.  * telnet:
  444.  */
  445.  
  446. - copyString:(char *)s {
  447.   id p = [Pasteboard new];
  448.   [p declareTypes:&NXAsciiPboard num:1 owner:self];
  449.   [p writeType:NXAsciiPboard data:s length:strlen(s)];
  450.   return self;
  451. }
  452.  
  453. - launchTerminal:(char *)program {
  454.   id p = [NXApp appSpeaker];
  455.   port_t t = NXPortFromName("Terminal",NULL);
  456.   int ok;
  457.   if (t==PORT_NULL) return self;
  458.   [p setSendPort:t];
  459.   [self copyString:program];
  460.   (void)[p msgPaste:&ok];
  461.   return self;
  462. }
  463.  
  464. - telnet:sender {
  465.     char p[1024];
  466.     sprintf(p,"telnet %s 3000\n",Site);
  467.     [self launchTerminal:p];
  468.     return self;
  469. }
  470.  
  471. - sendComments:sender {
  472.     return self;
  473. }
  474.  
  475. - print:sender {
  476.     static int p = 0;
  477.     if (!p){
  478.         p++;
  479.         [[NXApp printInfo] setScalingFactor:.9];
  480.     }
  481.     return [_text printPSCode:sender];
  482. }
  483.  
  484. - pageLayout:sender {
  485.     return [NXApp runPageLayout:sender];
  486. }
  487.  
  488. + new {
  489.     me = self = [[Storm alloc] init];
  490.     return self;
  491. }
  492.  
  493. - free {
  494.     [self logout:self];
  495.     return [super free];
  496. }
  497.  
  498.  
  499. - appDidInit:sender {
  500.     openDefaults();
  501.     if (FirstUse()) [license show:self];
  502.     [attachB performClick:sender];
  503.     return self;
  504. }
  505.  
  506. - appWillTerminate:sender {
  507.     [self logout:self];
  508.     System("/bin/rm -rf /tmp/W_maps /tmp/W_scratch &");
  509.     writeDefaults();
  510.     return self;
  511. }
  512.  
  513. - (int)browser:sender fillMatrix:matrix inColumn:(int)column {
  514.     char *s = "Main";
  515.     if (column>0){
  516.         id c;
  517.         c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
  518.         s = [c get];
  519.     }
  520.     setMenu(s);
  521.     return numItem(s);
  522. }
  523.  
  524. - browser:sender loadCell:c atRow:(int)row inColumn:(int)column {
  525.     [c setStringValueNoCopy:(void *)curMenuItem(row)];
  526.     return self;
  527. }
  528.  
  529. - browserDidScroll:sender {
  530.     static int pc = -1;
  531.     int c = [browser firstVisibleColumn];
  532.     ensurelogin();
  533.     if (pc == c) return self;
  534.     pc = c;
  535.     if (c == 0) Put("m\n"), Flush("Change scroll"), setMenu("Main");
  536.     else
  537.     [[[browser matrixInColumn:0] selectedCell] click:self];
  538.     return self;
  539. }
  540.  
  541.  
  542. @end
  543.